package com.fr.chart.math;

import com.fr.base.XMLable;
import com.fr.base.core.json.JSONException;
import com.fr.base.core.json.JSONObject;
import com.fr.base.xml.XMLPrintWriter;
import com.fr.base.xml.XMLableReader;
import java.awt.geom.Arc2D;
import java.awt.geom.Arc2D.Double;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.awt.geom.Point2D.Float;

public final class Projection
  implements XMLable
{
  private static final long serialVersionUID = 1L;
  public static final String XML_TAG = "Projection";
  private byte mode = 2;
  public static final byte ORTHO = 0;
  public static final byte PERSPECTIVE = 1;
  public static final byte RIGHT_ANGLE = 2;
  private int elevation = 15;
  private int rotation = 20;
  private int focus = 800;
  private boolean need_cal = true;
  private double sin_theta_alpha;
  private double cos_theta_alpha;
  private double sin_theta_beta;
  private double cos_theta_beta;

  public int getFocus()
  {
    return this.focus;
  }

  public void setFocus(int paramInt)
  {
    this.focus = paramInt;
  }

  public int getRotation()
  {
    return this.rotation;
  }

  public void setRotation(int paramInt)
  {
    this.rotation = paramInt;
    if (!(this.need_cal))
      this.need_cal = true;
  }

  public int getElevation()
  {
    return this.elevation;
  }

  public void setElevation(int paramInt)
  {
    this.elevation = paramInt;
    if (!(this.need_cal))
      this.need_cal = true;
  }

  public byte getMode()
  {
    return this.mode;
  }

  public void setMode(byte paramByte)
  {
    this.mode = paramByte;
  }

  public Point2D projectee(double paramDouble1, double paramDouble2, double paramDouble3)
  {
    calculateSINCOS();
    if (this.mode == 0)
      return ortho_projectee(paramDouble1, paramDouble2, paramDouble3);
    if (this.mode == 1)
      return perspective_projectee(paramDouble1, paramDouble2, paramDouble3);
    if (this.mode == 2)
      return right_angle_projectee(paramDouble1, paramDouble2, paramDouble3);
    return new Point2D.Double(paramDouble1, paramDouble2);
  }

  public Arc2D projecteeArc(double paramDouble1, double paramDouble2, double paramDouble3, double paramDouble4)
  {
    calculateSINCOS();
    double d = this.focus / (this.sin_theta_alpha * paramDouble1 + this.focus);
    Arc2D.Double localDouble = new Arc2D.Double(-paramDouble2 * d, -paramDouble2 * d * this.sin_theta_alpha + paramDouble1 * this.cos_theta_alpha * d, 2.0D * paramDouble2 * d, 2.0D * paramDouble2 * d * this.sin_theta_alpha, paramDouble3 + this.rotation, paramDouble4, 2);
    return localDouble;
  }

  private void calculateSINCOS()
  {
    if (!(this.need_cal))
      return;
    this.sin_theta_alpha = Math.sin(Math.toRadians(this.elevation));
    this.cos_theta_alpha = Math.cos(Math.toRadians(this.elevation));
    this.sin_theta_beta = Math.sin(Math.toRadians(-this.rotation));
    this.cos_theta_beta = Math.cos(Math.toRadians(-this.rotation));
    this.need_cal = false;
  }

  private Point2D perspective_projectee(double paramDouble1, double paramDouble2, double paramDouble3)
  {
    double d1 = paramDouble1 * this.cos_theta_beta + paramDouble3 * this.sin_theta_beta;
    double d2 = -paramDouble1 * this.sin_theta_alpha * this.sin_theta_beta + paramDouble2 * this.cos_theta_alpha + paramDouble3 * this.sin_theta_alpha * this.cos_theta_beta;
    double d3 = this.focus / (this.cos_theta_alpha * this.sin_theta_beta * paramDouble1 + this.sin_theta_alpha * paramDouble2 - this.cos_theta_alpha * this.cos_theta_beta * paramDouble3 + this.focus);
    return new Point2D.Float((float)(d1 * d3), (float)(d2 * d3));
  }

  private Point2D ortho_projectee(double paramDouble1, double paramDouble2, double paramDouble3)
  {
    double d1 = paramDouble1 * this.cos_theta_beta + paramDouble3 * this.sin_theta_beta;
    double d2 = -paramDouble1 * this.sin_theta_alpha * this.sin_theta_beta + paramDouble2 * this.cos_theta_alpha + paramDouble3 * this.sin_theta_alpha * this.cos_theta_beta;
    return new Point2D.Float((float)d1, (float)d2);
  }

  private Point2D right_angle_projectee(double paramDouble1, double paramDouble2, double paramDouble3)
  {
    double d1 = paramDouble1 + paramDouble3 * this.sin_theta_beta * 0.5D;
    double d2 = paramDouble2 + paramDouble3 * this.sin_theta_alpha * 0.5D;
    return new Point2D.Float((float)d1, (float)d2);
  }

  public void readXML(XMLableReader paramXMLableReader)
  {
    if (paramXMLableReader.isAttr())
    {
      String str;
      if ((str = paramXMLableReader.getAttr("mode")) != null)
        setMode(Byte.parseByte(str));
      if ((str = paramXMLableReader.getAttr("elevation")) != null)
        setElevation(Integer.parseInt(str));
      if ((str = paramXMLableReader.getAttr("rotation")) != null)
        setRotation(Integer.parseInt(str));
      if ((str = paramXMLableReader.getAttr("focus")) != null)
        setFocus(Integer.parseInt(str));
    }
  }

  public void writeXML(XMLPrintWriter paramXMLPrintWriter)
  {
    paramXMLPrintWriter.startTAG("Projection").attr("mode", this.mode).attr("elevation", this.elevation).attr("rotation", this.rotation).attr("focus", this.focus).end();
  }

  public Object clone()
    throws CloneNotSupportedException
  {
    Projection localProjection = (Projection)super.clone();
    return localProjection;
  }

  public boolean equals(Object paramObject)
  {
    if (!(paramObject instanceof Projection))
      return false;
    Projection localProjection = (Projection)paramObject;
    if (localProjection.getElevation() != getElevation())
      return false;
    if (localProjection.getRotation() != getRotation())
      return false;
    if (localProjection.getFocus() != getFocus())
      return false;
    return (localProjection.getMode() == getMode());
  }

  public JSONObject toJSONObject()
    throws JSONException
  {
    JSONObject localJSONObject = new JSONObject();
    localJSONObject.put("mode", this.mode);
    localJSONObject.put("elevation", this.elevation);
    localJSONObject.put("focus", this.focus);
    localJSONObject.put("rotation", this.rotation);
    localJSONObject.put("need_cal", this.need_cal);
    localJSONObject.put("sin_theta_alpha", this.sin_theta_alpha);
    localJSONObject.put("sin_theta_beta", this.sin_theta_beta);
    localJSONObject.put("cos_theta_alpha", this.cos_theta_alpha);
    localJSONObject.put("cos_theta_beta", this.cos_theta_beta);
    return localJSONObject;
  }
}